package com.wanwu.channel.notify.controller;


import com.alibaba.fastjson.JSON;
import com.alipay.api.internal.util.AlipaySignature;
import com.wanwu.channel.common.enums.BusinessCodeEnum;
import com.wanwu.channel.common.enums.ExceptionEnum;
import com.wanwu.channel.common.enums.TradeStatusEnum;
import com.wanwu.channel.common.exception.SystemException;
import com.wanwu.channel.common.util.LogUtil;
import com.wanwu.channel.core.util.apollo.ApolloMerchantUtil;
import com.wanwu.channel.dao.entity.ChannelMerchantInfoEntity;
import com.wanwu.channel.notify.config.AlipayConfig;
import com.wanwu.channel.notify.process.AlipayNotifyProcess;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

@RestController
@RequestMapping("/alipay/apppay")
public class AlipayAppPayController {

    private static Logger logger = LoggerFactory.getLogger(AlipayAppPayController.class);

    @Autowired
    private AlipayConfig alipayConfig;

    @Autowired
    private AlipayNotifyProcess alipayNotifyProcess;

    @Resource
    private ApolloMerchantUtil apolloMerchantUtil;

    @RequestMapping(value = "/common/notify", method = RequestMethod.POST)
    public String appPayNotify(HttpServletRequest request) {
        try {
            //解析请求参数
            Map<String, String> paramsMap = this.getRequestParams(request);
            LogUtil.info(logger, "接收到【支付宝直连支付】通用回调请求，{0}", JSON.toJSONString(paramsMap));
            //验证签名
            boolean signVerified = AlipaySignature.rsaCheckV1(paramsMap, alipayConfig.getAlipayPublicKey(), alipayConfig.getCharsetUtf8(), alipayConfig.getSignTypeRsa2());

            if (!signVerified) {
                throw new SystemException(ExceptionEnum.E10009);
            }
            //bizCode作为数据库参数必须传,会调到这个回调的只有线上已经有的万里目业务,故这里设置为万里目
            alipayNotifyProcess.commonNotify(paramsMap, BusinessCodeEnum.WANLIMU.getBizCode(), 0);
            LogUtil.info(logger, "【支付宝直连支付】通用回调处理成功，bizOrderNo:{0}", paramsMap.get("out_trade_no"));
            return TradeStatusEnum.SUCCESS.name().toLowerCase();
        } catch (Exception e) {
            LogUtil.error(logger, e, "处理【支付宝直连支付】结果回调失败");
            return TradeStatusEnum.FAIL.name();
        }
    }

    /**
     * 新回调处理
     *
     * @param request
     * @param payType
     * @param merchantNo
     * @return
     */
    @RequestMapping(value = "/common/notify/{payType}/{merchantNo}", method = RequestMethod.POST)
    public String appNewPayNotify(HttpServletRequest request, @PathVariable String payType, @PathVariable String merchantNo) {
        try {
            //解析请求参数
            Map<String, String> paramsMap = this.getRequestParams(request);
            LogUtil.info(logger, "接收到【支付宝直连支付】通用回调请求new，{0}", JSON.toJSONString(paramsMap));
            //验证签名
            ChannelMerchantInfoEntity entity = apolloMerchantUtil.selectByPayChannelAndMerchantNo(payType, merchantNo);
            String aliPubKey = null == entity ? alipayConfig.getAlipayPublicKey() : entity.getThirdPayPubKey();
            boolean signVerified = AlipaySignature.rsaCheckV1(paramsMap, aliPubKey, alipayConfig.getCharsetUtf8(), alipayConfig.getSignTypeRsa2());

            if (!signVerified) {
                throw new SystemException(ExceptionEnum.E10009);
            }
            //bizCode用于从库里查询时的参数,线上已有业务全为万里目,且会调到这个回调方法的都是已有数据,故这里全部配置为wanlimu_code
            alipayNotifyProcess.commonNotify(paramsMap, BusinessCodeEnum.WANLIMU.getBizCode(), 0);
            LogUtil.info(logger, "【支付宝直连支付】通用回调处理成功，bizOrderNo:{0}", paramsMap.get("out_trade_no"));
            return TradeStatusEnum.SUCCESS.name().toLowerCase();
        } catch (Exception e) {
            LogUtil.error(logger, e, "处理【支付宝直连支付】结果回调失败");
            return TradeStatusEnum.FAIL.name();
        }
    }

    /**
     * 平台化支付回调处理
     *
     * @param request    请求报文
     * @param payType    支付渠道
     * @param merchantNo 商户号
     * @param bizCode    业务号
     */
    @RequestMapping(value = "/common/notify/{payType}/{bizCode}/{merchantNo}", method = RequestMethod.POST)
    public String appNewPayNotify(HttpServletRequest request, @PathVariable String payType, @PathVariable String bizCode, @PathVariable String merchantNo) {
        try {
            //解析请求参数
            Map<String, String> paramsMap = this.getRequestParams(request);
            LogUtil.info(logger, "接收到【支付宝直连支付】通用回调请求plat new，{0}", JSON.toJSONString(paramsMap));
            //验证签名
            ChannelMerchantInfoEntity entity = apolloMerchantUtil.selectByPayChannelAndMerchantNoAndBizCode(payType, merchantNo, bizCode);
            String aliPubKey = null == entity ? alipayConfig.getAlipayPublicKey() : entity.getThirdPayPubKey();
            boolean signVerified = AlipaySignature.rsaCheckV1(paramsMap, aliPubKey, alipayConfig.getCharsetUtf8(), alipayConfig.getSignTypeRsa2());

            if (!signVerified) {
                throw new SystemException(ExceptionEnum.E10009);
            }
            alipayNotifyProcess.commonNotify(paramsMap, bizCode, 1);
            LogUtil.info(logger, "【支付宝直连支付】通用回调处理成功，bizOrderNo:{0}", paramsMap.get("out_trade_no"));
            return TradeStatusEnum.SUCCESS.name().toLowerCase();
        } catch (Exception e) {
            LogUtil.error(logger, e, "处理【支付宝直连支付】结果回调失败");
            return TradeStatusEnum.FAIL.name();
        }
    }


    /**
     * @param request
     * @return
     */
    private Map<String, String> getRequestParams(HttpServletRequest request) {

        Map<String, String> params = new HashMap<String, String>();
        if (null != request) {
            Set<String> paramsKey = request.getParameterMap().keySet();
            for (String key : paramsKey) {
                params.put(key, request.getParameter(key));
            }
        }
        return params;
    }

}
